!****************************************************
!  task partition only on two dimensions <Z,Y-split,X-split>
!                       i.e. in loop split<k,j-split,i-split> 
!  usage: make see fdag in makefile 
!***************************************************
      subroutine sws_2d5p_core(args)
      use dag_parallel
      implicit none
      include "init.for"
#include "aceMesh_runtime_f.h"
#define alpha 0.0876
#define beta 0.0765

      type(ARG_TYPE) :: args
      integer :: starti,endi,startj,endj,it
      integer :: i,j,dest,src
#ifdef _PROFILING
      integer(8),dimension(64)::slave_dma_count,slave_comp_count,slave_exec_count
      common /time/slave_dma_count,slave_comp_count,slave_exec_count
      integer(8) dma_start,dma_end,comp_start,comp_end,exec_start,exec_end
      integer::my_id
      integer(8) :: slave_gld_count,gld_start,gld_end
      common /gld/slave_gld_count
#endif

#ifdef _MMEM
#ifdef _PROFILING
      call get_myid(my_id)
      call rtcc(exec_start)
      call penv_slave2_gld_count(gld_start)
#endif
      !print *,"before"
      starti = args%starti
      endi = args%endi
      startj = args%startj
      endj = args%endj
      it = args%iter
      dest = mod(it,2)+1
      src  = mod(it+1,2)+1
      do i=starti,endi
      do j=startj,endj
        A(j,i,dest) = alpha * A(j,i,src) +beta * (A(j,i+1,src) + A(j+1,i,src)+ A(j,i-1,src)+ A(j-1,i,src))
      enddo
      enddo
#ifdef _PROFILING
      call penv_slave2_gld_count(gld_end)
      slave_gld_count = slave_gld_count+(gld_end-gld_start)
!      print *,slave_gld_count,gld_end,gld_start
      call rtcc(exec_end)
      slave_exec_count(my_id)=slave_exec_count(my_id)+(exec_end-exec_start)
#endif
      !print *,"end"
#else
      real(8), dimension(1:BLKY,1:BLKX):: a_data_lhs, a_data_rhs
      pointer(p_a_data_lhs,a_data_lhs)
      pointer(p_a_data_rhs,a_data_rhs)

      real(8), dimension(1:BLKY,1:BLKX,1:2):: a_slave
      real(8), dimension(BLKY):: a_slave_us, a_slave_ds
      real(8), dimension(BLKX):: a_slave_ls, a_slave_rs
#ifdef _UNROLL
      real(8) tmpji,tmpj1i,tmpj2i,tmpj3i,tmp,tmp1,tmp2,tmp3,tmp4,tmp5,tmp6,tmp7
#endif
      integer :: tsize, bsize, stride
 
      integer :: reply
      integer :: dma_num
      integer :: rhs_no 
      integer :: lhs_no
      integer,dimension (2) :: tileno,varno,reuse
      common /local_region/reuse,varno,tileno,a_slave,a_slave_us,a_slave_ds,a_slave_ls,a_slave_rs,tsize,bsize,stride
      
      !$omp threadprivate (/local_region/)
#ifdef _PROFILING
      call get_myid(my_id)
      !print *, my_id
      !call penv_slave2_gld_count(gld_start)
      call rtcc(exec_start)
#endif
      starti= args%starti
      endi  = args%endi
      startj= args%startj
      endj  = args%endj
      it  = args%iter
      dest = mod(it,2)+1
      src  = mod(it+1,2)+1
     
      !update data
      dma_num= 0
      reply  = 0
      !update core data
      tsize  = BLKX*BLKY*8
      stride = (SIZEX-BLKX)*8
      bsize  = BLKX*8
      !print *,"before dma_get"
#ifdef _PROFILING
      call rtcc(dma_start)
      !print *,"dmastart:",dma_start
#endif
#ifdef _LDMM
      tileno(1)=startj/BLKY
      tileno(2)=starti/BLKX
      addr1=loc(A(1,1,dest))
      addr2=loc(tileno)
      call slave_ldm_postreq_tile_swf(%val(addr1),2,%val(addr2),OUT)
      addr1=loc(A(1,1,src))
      call slave_ldm_postreq_tile_swf(%val(addr1),2,%val(addr2),IN)
      addr1=loc(varno)
      addr2=loc(reuse)
      call slave_ldm_getreq_tile_swf(%val(addr1),%val(addr2))
      lhs_no=varno(1)+1
      rhs_no=varno(2)+1
      p_a_data_lhs = loc(a_slave(1,1,lhs_no))
      p_a_data_rhs = loc(a_slave(1,1,rhs_no))
      if(reuse(2).eq.0)then
        call athread_get(0,A(startj,starti,src),a_slave(1,1,rhs_no),tsize,reply,0,stride,bsize)
        dma_num=dma_num+1
      endif
#else
      rhs_no=2
      lhs_no=1
      p_a_data_lhs = loc(a_slave(1,1,lhs_no))
      p_a_data_rhs = loc(a_slave(1,1,rhs_no))

      call athread_get(0,A(startj,starti,src),a_slave(1,1,rhs_no),tsize,reply,0,stride,bsize)
      dma_num=dma_num+1
#endif
      !update up and down shade data
      call athread_get(0,A(startj-1,starti,src),a_slave_us(1),BLKY*8,reply,0,(SIZEX-1)*8,8)
      call athread_get(0,A(endj+1,starti,src),a_slave_ds(1),BLKY*8,reply,0,(SIZEX-1)*8,8)
      !update left and right shade data
      call athread_get(0,A(startj,starti-1,src),a_slave_ls(1),BLKX*8,reply,0,0,0)
      call athread_get(0,A(startj,endi+1,src),a_slave_rs(1),BLKX*8,reply,0,0,0)
      dma_num=dma_num+4
      call reply_wait(reply,dma_num)

#ifdef _PROFILING
      call rtcc(dma_end)
      slave_dma_count(my_id)=slave_dma_count(my_id)+(dma_end-dma_start)
      call penv_slave2_gld_count(gld_start)
      !print *,dma_end-dma_start
      call rtcc(comp_start)
#endif
      !compute
      !compute core
      do i=2,BLKX-1
#ifdef _UNROLL
      do j=2,BLKY-1,4
        tmpji=a_data_rhs(j, i)
        tmpj1i=a_data_rhs(j+1,i)
        tmpj2i=a_data_rhs(j+2,i)
        tmpj3i=a_data_rhs(j+3,i)
        a_data_lhs(j,i)=alpha*tmpji+beta*&
                    ( a_data_rhs(j-1,i)+tmpj1i+&
                    a_data_rhs(j,i-1)+a_data_rhs(j,i+1) )
        a_data_lhs(j+1,i)=alpha*tmpj1i+beta*&
                    ( tmpji+tmpj2i+&
                    a_data_rhs(j+1,i-1)+a_data_rhs(j+1,i+1) )
        a_data_lhs(j+2,i)=alpha*tmpj2i+beta*&
                    ( tmpj1i+tmpj3i+&
                    a_data_rhs(j+2,i-1)+a_data_rhs(j+2,i+1) )
        a_data_lhs(j+3,i)=alpha*tmpj3i+beta*&
                    ( tmpj2i+a_slave(j+4,i)+&
                    a_data_rhs(j+3,i-1)+a_data_rhs(j+3,i+1) )
#else
      do j=2,BLKY-1
        a_data_lhs(j,i)=alpha*a_data_rhs(j,i)+beta*&
                    ( a_data_rhs(j-1,i)+a_data_rhs(j+1,i)+&
                    a_data_rhs(j,i-1)+a_data_rhs(j,i+1) )
#endif
      enddo
      enddo 

      !compute up and down line
#ifdef _UNROLL
      do i=2,BLKX-1,2
        tmp=a_slave(1,i)
        tmp1=a_slave(1,i+1)
        a_data_lhs(1,i)=alpha*tmp + beta*&
                    (a_slave_us(i)+a_data_rhs(1,i-1)+&
                    tmp1+a_data_rhs(2,i))
        a_data_lhs(1,i+1)=alpha*tmp1 + beta*&
                    (a_slave_us(i+1)+tmp+&
                    a_data_rhs(1,i+2)+a_data_rhs(2,i+1))
!      enddo
!      do i=2,BLKX-1,2
        tmp2=a_data_rhs(BLKY,i)
        tmp3=a_data_rhs(BLKY,i+1)
        a_data_lhs(BLKY,i)=alpha*tmp2 + beta*&
                    (a_slave_ds(i) +a_data_rhs(BLKY,i-1)+&
                    tmp3+a_data_rhs(BLKY-1,i))
        a_data_lhs(BLKY,i+1)=alpha*tmp3 + beta*&
                    (a_slave_ds(i+1) +tmp2+&
                    a_data_rhs(BLKY,i+2)+a_data_rhs(BLKY-1,i+1))
      enddo
#else
      do i=2,BLKX-1
        a_data_lhs(1,i)=alpha*a_data_rhs(1,i) + beta*&
                    (a_slave_us(i)+a_data_rhs(1,i-1)+&
                    a_data_rhs(1,i+1)+a_data_rhs(2,i))
        a_data_lhs(BLKY,i)=alpha*a_data_rhs(BLKY,i) + beta*&
                    (a_slave_ds(i) +a_data_rhs(BLKY,i-1)+&
                    a_data_rhs(BLKY,i+1)+a_data_rhs(BLKY-1,i))
      enddo
#endif
      !compute left and right line
#ifdef _UNROLL
      tmp4=a_slave(j,1)
      tmp5=a_slave(j+1,1)
      do j=2,BLKY-1,2 
        a_data_lhs(j,1)=alpha*a_data_rhs(j,1) +beta*&
                    (a_slave_ls(j)+a_data_rhs(j-1,1)+&
                    tmp5+a_data_rhs(j,2))
        a_data_lhs(j+1,1)=alpha*tmp5 +beta*&
                    (a_slave_ls(j+1)+a_data_rhs(j,1)+&
                    a_data_rhs(j+2,1)+a_data_rhs(j+1,2))
      enddo
      tmp6=a_data_rhs(j,BLKX)
      tmp7=a_data_rhs(j+1,BLKX)
      do j=2,BLKY-1,2
        a_data_lhs(j,BLKX)=alpha*a_data_rhs(j,BLKX) +beta*&
                    (a_slave_rs(j)+a_data_rhs(j-1,BLKX)+&
                    a_data_rhs(j+1,BLKX)+a_data_rhs(j,BLKX-1))
        a_data_lhs(j+1,BLKX)=alpha*a_data_rhs(j+1,BLKX) +beta*&
                    (a_slave_rs(j+1)+a_data_rhs(j,BLKX)+&
                    a_data_rhs(j+2,BLKX)+a_data_rhs(j+1,BLKX-1))
      enddo
#else
      do j=2,BLKY-1
        a_data_lhs(j,1)=alpha*a_data_rhs(j,1) +beta*&
                    (a_slave_ls(j)+a_data_rhs(j-1,1)+&
                    a_data_rhs(j+1,1)+a_data_rhs(j,2))
        a_data_lhs(j,BLKX)=alpha*a_data_rhs(j,BLKX) +beta*&
                    (a_slave_rs(j)+a_data_rhs(j-1,BLKX)+&
                    a_data_rhs(j+1,BLKX)+a_data_rhs(j,BLKX-1))
      enddo
#endif
      !compute point corner
      a_data_lhs(1,1)=alpha*a_data_rhs(1,1)+beta*&
                    (a_slave_us(1)+a_slave_ls(1)+&
                    a_data_rhs(2,1)+a_data_rhs(1,2))
      a_data_lhs(1,BLKX)=alpha*a_data_rhs(1,BLKX) + beta*&
                    ( a_slave_us(BLKX)+ a_slave_rs(1) +&
                    a_data_rhs(1,BLKX-1)+ a_data_rhs(2,BLKX) )
      a_data_lhs(BLKY,1)=alpha*a_data_rhs(BLKY,1) + beta*&
                    ( a_slave_ls(BLKY)+ a_slave_ds(1) +&
                    a_data_rhs(BLKY-1,1)+ a_data_rhs(BLKY,2) )
      a_data_lhs(BLKY,BLKX)=alpha*a_data_rhs(BLKY,BLKX) + beta*&
                    (a_data_rhs(BLKY-1,BLKX)+a_slave_ds(BLKX)+&
                    a_slave_rs(BLKY)+a_data_rhs(BLKY,BLKX-1))
#ifdef _PROFILING
      call rtcc(comp_end)
      call penv_slave2_gld_count(gld_end)
      slave_comp_count(my_id)=slave_comp_count(my_id)+(comp_end-comp_start)
      slave_gld_count = slave_gld_count+(gld_end-gld_start)
      !print *,slave_gld_count,gld_end,gld_start
      call rtcc(dma_start)
#endif
      !write back
      reply=0
      call athread_put(0,a_slave(1,1,lhs_no),A(startj,starti,dest),tsize,reply,stride,bsize)
      call reply_wait(reply,1)

#ifdef _PROFILING
      call rtcc(dma_end)
      call penv_slave2_gld_count(gld_end)
      !slave_gld_count = slave_gld_count+(gld_end-gld_start)
      slave_dma_count(my_id)=slave_dma_count(my_id)+(dma_end-dma_start)
      slave_exec_count(my_id)=slave_exec_count(my_id)+(dma_end-exec_start)
      !print *,slave_dma_count(my_id),slave_exec_count(my_id),dma_end,exec_start
#endif

#endif
      end subroutine 
